﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace hamster
{
    class Firefly
    {
        public const float MIN_FLARE = .1f;
        public const float MAX_FLARE = 10;

        Texture2D lensFlareTexture;
        Texture2D glowTexture;
        Effect glowEffect;
        public Vector3 position;
        public Vector3 velocity; 
        public Vector3 end_target;
        private Player player_;
        public float brightness = 0f;
        
        public Firefly(Player player)
        {
            end_target = Vector3.Zero;
            velocity = Vector3.Zero;
            position = Vector3.Zero;
            player_ = player;
        }

        public void Reload(ContentManager content)
        {
            if (glowEffect != null) glowEffect.Dispose();
            if (lensFlareTexture != null) lensFlareTexture.Dispose();
            if (glowTexture != null) glowTexture.Dispose();
            if (lens_a != null) lens_a.Dispose();
            Create(content);
        }

        Texture2D lens_a;

        public void Create(ContentManager content)
        {
            glowEffect = content.Load<Effect>("Filefly");
            lensFlareTexture = content.Load<Texture2D>("flare");
            glowTexture = content.Load<Texture2D>("fairy");
            lens_a = content.Load<Texture2D>("lens_a");
            
            position = Game1._player.position;
        }

        float angle = 0f;
        float radius_prev = 0f;
        float radius = 0f;
        float radius_next = 0f;
        float next_think = 0f;
        public void Update(float dt)
        {
            brightness = player_.brightness +Game1.Sin(radius + Game1.time_duration * 3f) * 0.15f;
            if (next_think > 1f)// || ((position - end_target).Length() < 1f))
            {
                radius_prev = radius_next;
                radius_next = 5f * Game1.RandomFloat + 1f;
                

                next_think = 0f;
            }


            radius = MathHelper.Lerp(radius_prev, radius_next, next_think);

            Vector3 target = Game1._player.position + Vector3.Normalize(new Vector3(Game1._player._viewRot.Y, -Game1._player._viewRot.X, 0));

            Vector3 vel = (target - position) * 2.51f;

            angle += dt * 3;
            Vector3 angleV = new Vector3(Game1.Sin(angle), Game1.Cos(radius + angle), 0f) * radius;
            velocity = vel + angleV;

            position += velocity * dt;
            next_think += dt;
 
        }

        public void DrawFlares(GraphicsDevice device)
        {
            Matrix world = Matrix.CreateTranslation(position.X, position.Y, position.Z);
            
            Vector3 ss = device.Viewport.Project(position, Game1.projectionMatrix, Game1.viewMatrix, Matrix.Identity);
            Vector2 lightproject = Vector2.One / 2 - new Vector2(ss.X / device.Viewport.Width, ss.Y / device.Viewport.Height);
        
            VertexPositionNormalTexture[] _debug = new VertexPositionNormalTexture[] {

                new VertexPositionNormalTexture { Position = new Vector3(-1f, -1f, 0f), TextureCoordinate = new Vector2(0,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, -1f, 0f), TextureCoordinate = new Vector2(1,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, 1f, 0f), TextureCoordinate = new Vector2(1,0) },

                new VertexPositionNormalTexture { Position = new Vector3(-1f, -1f, 0f), TextureCoordinate = new Vector2(0,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, 1f, 0f), TextureCoordinate = new Vector2(1,0) },
                new VertexPositionNormalTexture { Position = new Vector3(-1f, 1f, 0f), TextureCoordinate = new Vector2(0,0) },
            };


            device.RenderState.DepthBufferWriteEnable = false;
            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.AlphaSourceBlend = Blend.One;
            device.RenderState.AlphaDestinationBlend = Blend.One;
            //device.RenderState.SourceBlend = Blend.One;
            device.RenderState.DestinationBlend = Blend.One;
            device.RenderState.BlendFunction = BlendFunction.Add;


            glowEffect.Parameters["View"].SetValue(Game1.viewMatrix);
            glowEffect.Parameters["World"].SetValue(world);
            glowEffect.Parameters["Projection"].SetValue(Game1.projectionMatrix);

            glowEffect.Parameters["UserTexture"].SetValue(lens_a);
            glowEffect.Begin();
            for (int i = 0; i < 10; i++)
            {
                
                float frac = (float)i / (float)10f;
                float scale = Game1.Cos(frac  *  6.14f) * 0.5f + 0.5f; ;
                Vector2 td = 10 * Vector2.Lerp(lightproject, -lightproject, frac);// 0.5f * Vector2.UnitX * i;// Vector2.Lerp(lightproject, Vector2.Zero, (float)i / (float)10f) * 101;
                td.X = -td.X;
               // td = lightproject - td;

                glowEffect.Parameters["LensPosition"].SetValue(new Vector4(td, scale, 0f));
                glowEffect.CommitChanges();

                glowEffect.CurrentTechnique.Passes[2].Begin();
                device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, _debug, 0, _debug.Length / 3);
                glowEffect.CurrentTechnique.Passes[2].End();
            }
            glowEffect.End();

            device.RenderState.AlphaBlendEnable = false;
            device.RenderState.DepthBufferWriteEnable = true;
            

            //world * Game1.
            //position
        }

        public void Draw(GraphicsDevice device)
        {
            VertexPositionNormalTexture[] _debug = new VertexPositionNormalTexture[] {

                new VertexPositionNormalTexture { Position = new Vector3(-1f, -1f, 0f), TextureCoordinate = new Vector2(0,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, -1f, 0f), TextureCoordinate = new Vector2(1,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, 1f, 0f), TextureCoordinate = new Vector2(1,0) },

                new VertexPositionNormalTexture { Position = new Vector3(-1f, -1f, 0f), TextureCoordinate = new Vector2(0,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, 1f, 0f), TextureCoordinate = new Vector2(1,0) },
                new VertexPositionNormalTexture { Position = new Vector3(-1f, 1f, 0f), TextureCoordinate = new Vector2(0,0) },
            };

            Matrix world = Matrix.CreateTranslation(position.X, position.Y, position.Z);

            device.RenderState.DepthBufferWriteEnable = false;
            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.AlphaSourceBlend = Blend.One;
            device.RenderState.AlphaDestinationBlend = Blend.One;
            //device.RenderState.SourceBlend = Blend.One;
            device.RenderState.DestinationBlend = Blend.One;
            device.RenderState.BlendFunction = BlendFunction.Add;

            glowEffect.Parameters["View"].SetValue(Game1.viewMatrix);
            glowEffect.Parameters["Projection"].SetValue(Game1.projectionMatrix);
            glowEffect.Parameters["UserTexture"].SetValue(glowTexture);
            glowEffect.Parameters["GlowIntensity"].SetValue( 1); 
            glowEffect.Begin();


            glowEffect.Parameters["World"].SetValue(Matrix.CreateScale(brightness * 0.5f) *  Matrix.CreateRotationZ(Game1.time_duration * 1.5f) * world);
            glowEffect.CommitChanges();

            glowEffect.CurrentTechnique.Passes[1].Begin();
            device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, _debug, 0, _debug.Length / 3);
            glowEffect.CurrentTechnique.Passes[1].End();

            glowEffect.Parameters["World"].SetValue(Matrix.CreateRotationZ(Game1.time_duration * -2.5f) * world);
            glowEffect.CommitChanges();
            glowEffect.CurrentTechnique.Passes[1].Begin();
            device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, _debug, 0, _debug.Length / 3);
            glowEffect.CurrentTechnique.Passes[1].End();

            glowEffect.End();

            device.RenderState.AlphaBlendEnable = false;
            device.RenderState.DepthBufferWriteEnable = true;
            

            DrawFlares(device);
        }



        public void DrawGlow(GraphicsDevice device)
        {

            VertexPositionNormalTexture[] _debug = new VertexPositionNormalTexture[] {

                new VertexPositionNormalTexture { Position = new Vector3(-1f, -1f, 0f), TextureCoordinate = new Vector2(0,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, -1f, 0f), TextureCoordinate = new Vector2(1,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, 1f, 0f), TextureCoordinate = new Vector2(1,0) },

                new VertexPositionNormalTexture { Position = new Vector3(-1f, -1f, 0f), TextureCoordinate = new Vector2(0,1) },
                new VertexPositionNormalTexture { Position = new Vector3(1f, 1f, 0f), TextureCoordinate = new Vector2(1,0) },
                new VertexPositionNormalTexture { Position = new Vector3(-1f, 1f, 0f), TextureCoordinate = new Vector2(0,0) },
            };

            //player_.brightness = 1;
            Matrix world = Matrix.CreateScale(MIN_FLARE + player_.brightness * (MAX_FLARE - MIN_FLARE))*Matrix.CreateTranslation(position.X, position.Y, position.Z);

            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.SourceBlend = Blend.SourceAlpha;
            device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

            glowEffect.Parameters["View"].SetValue(Game1.viewMatrix);
            glowEffect.Parameters["Projection"].SetValue(Game1.projectionMatrix);
            glowEffect.Parameters["World"].SetValue(world);
            glowEffect.Parameters["UserTexture"].SetValue(lensFlareTexture);
            glowEffect.Begin();

            glowEffect.CurrentTechnique.Passes[0].Begin();
            device.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList,_debug,0,_debug.Length / 3);
            glowEffect.CurrentTechnique.Passes[0].End();

            glowEffect.End();
             
            device.RenderState.AlphaBlendEnable = false;
        }
    }
}
